package com.example.hosptialtag.service;

import com.example.hosptialtag.pojo.Bind;
import com.example.hosptialtag.pojo.Patient;
import com.example.hosptialtag.pojo.Tag;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Service;
import org.springframework.ui.Model;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * @Author liuyuhao&caiang
 * @Date 2022/2/21
 */

@Service
public class BindService {

    @Autowired
    private final JdbcTemplate jdbcTemplate;
    @Autowired
    private PatientService patientService;
    @Autowired
    private TagService tagService;
    @Autowired
    private RedisService redisService;

    public BindService(JdbcTemplate jdbcTemplate) {
        this.jdbcTemplate = jdbcTemplate;
    }

    private String sql;

    public String createBind(int bind_patient_id, int bind_tag_id,  String bind_start_time, String bind_end_time,
                             int oid, int role, Model model) {
        String flag = isPatientAndTagExist(bind_patient_id,bind_tag_id);//判断病人和标签是否存在
        if((bind_tag_id == 1 || bind_tag_id == 2)&&isSex(bind_patient_id)){
            model.addAttribute("bp_message", "病人已有绑定的性别标签");
            return getBindPage(bind_patient_id, bind_tag_id, oid, role, model);
        }
        if(bindExist(bind_patient_id,bind_tag_id)){//判断该病人和标签是否已经存在绑定关系
            if(bindDelete(bind_patient_id,bind_tag_id)){//已删除
                jdbcTemplate.update("update bind set bind_patient_id = ?, bind_tag_id = ?, bind_start_time = ?, bind_end_time = ?, bind_delete = 0 " +
                        "where bind_patient_id = ? and bind_tag_id = ?;", bind_patient_id, bind_tag_id, bind_start_time, bind_end_time, bind_patient_id, bind_tag_id);
                model.addAttribute("pb_message", "绑定成功");
                return getBindPageByPatientId(bind_patient_id, model);
            }
            model.addAttribute("bp_message", "该绑定已经存在");
            return getBindPage(bind_patient_id, bind_tag_id, oid, role, model);
        }
        else{
            if(flag == "0") {
                jdbcTemplate.update("insert into bind(bind_patient_id, bind_tag_id, bind_start_time, bind_end_time)\n" +
                        "values(?,?,?,?);", bind_patient_id, bind_tag_id, bind_start_time, bind_end_time);
//                redisService.delete("bpiFindbti"+Integer.toString(bind_patient_id));//删除该病人的缓存
//                redisService.delete("btiFindbpi"+Integer.toString(bind_tag_id));//删除该标签的缓存
                model.addAttribute("bp_message", "绑定成功");
                return getBindPage(bind_patient_id, bind_tag_id, oid, role, model);
            }
            else{
                model.addAttribute("bp_message", "标签或病人不存在");
                return getBindPage(bind_patient_id, bind_tag_id, oid, role, model);
            }
        }
    }

    public String createBindForever(int bind_patient_id, int bind_tag_id, Model model) {
        String flag = isPatientAndTagExist(bind_patient_id,bind_tag_id);//判断病人和标签是否存在
        if(bindExist(bind_patient_id,bind_tag_id)){//判断该病人和标签是否已经存在绑定关系
            return "该绑定已经存在";
        }
        else {
            if (flag == "0") {
                jdbcTemplate.update("insert into bind(bind_patient_id, bind_tag_id)\n" +
                        "values(?,?);", bind_patient_id, bind_tag_id);
//                redisService.delete("bpiFindbti"+Integer.toString(bind_patient_id));//删除该病人的缓存
//                redisService.delete("btiFindbpi"+Integer.toString(bind_tag_id));//删除该标签的缓存
                return "index";
            } else {
                return flag;
            }
        }
    }

    public String isPatientAndTagExist(int patient_id, int tag_id){//封装方法——添加绑定前确定病人是否存在，确定标签是否存在
        int patientFlag = patientService.getPatientsCountByPatientId(patient_id);
        int tagFlag = tagService.getTagsCountByTagId(tag_id);
        if(patientFlag != 0 && tagFlag != 0)
            return "0";//都存在
        return "该病人或标签都不存在，请检查后重新输入";
    }

    public boolean bindExist(int bind_patient_id, int bind_tag_id){//封装方法——病人和标签是否存在绑定关系，不允许重复绑定
        if(jdbcTemplate.queryForObject("select count(1) from bind where bind_patient_id = "+ Integer.toString(bind_patient_id)+" and bind_tag_id = " + bind_tag_id, Integer.class)>0){
            return true;
        }
        return false;
    }

    public boolean bindDelete(int bind_patient_id, int bind_tag_id){//封装方法——病人和标签存在绑定关系是否逻辑删除
        if(jdbcTemplate.queryForObject("select bind_delete from bind where bind_patient_id = "+ Integer.toString(bind_patient_id)+" and bind_tag_id = " + bind_tag_id, Integer.class)>0){
            return true;
        }
        return false;
    }

    public String updateBind(int bind_id, String bind_start_time, String bind_end_time, int oid, int role, Model model) {
        jdbcTemplate.update("update bind set bind_start_time = ?, bind_end_time = ? where bind_id = ?;",
                bind_start_time, bind_end_time, bind_id);
        model.addAttribute("bp_message", "修改成功");
        String sql = "select * from bind where bind_id = "+ bind_id;
        RowMapper<Bind> rowBindMapper=new BeanPropertyRowMapper<Bind>(Bind.class);
        Bind bind = jdbcTemplate.queryForObject(sql, rowBindMapper);
        model.addAttribute("bind", bind);
        RowMapper<Patient> rowPatientMapper=new BeanPropertyRowMapper<Patient>(Patient.class);
        Patient patient = jdbcTemplate.queryForObject("select * from tb_patient where id = ?", rowPatientMapper, bind.getBind_patient_id());
        model.addAttribute("patient", patient);
        RowMapper<Tag> rowTagMapper=new BeanPropertyRowMapper<Tag>(Tag.class);
        Tag tag = jdbcTemplate.queryForObject("select * from tag where tag_id = ?", rowTagMapper,bind.getBind_tag_id());
        model.addAttribute("tag", tag);
        return "forward:bindPage";
//            redisService.delete("bpiFindbti"+Integer.toString(bind_patient_id));//删除该病人的缓存
//            redisService.delete("btiFindbpi"+Integer.toString(bind_tag_id));//删除该标签的缓存

    }

    public String deleteBindById(int bind_id, int oid, int role, Model model) {
        jdbcTemplate.update("update bind set bind_delete = 1 where bind_id = ?",bind_id);
        List  <Map<String, Object>> binds= jdbcTemplate.queryForList("select * from bind where bind_id = ?",bind_id);
        for(int i=0;i<binds.size();i++){
            Map bindMap=binds.get(i);
//            redisService.delete("bpiFindbti"+Integer.toString((Integer) bindMap.get("bind_patient_id")));//删除该病人的缓存
//            redisService.delete("btiFindbpi"+Integer.toString((Integer) bindMap.get("bind_tag_id")));//删除该标签的缓存
        }

        return "index";
    }

    public void deleteBindByPatientId(int bind_patient_id, Model model) {
        jdbcTemplate.update("update bind set bind_delete = 1 where bind_patient_id = ?", bind_patient_id);
    }

    public void deleteBindByTagId(int bind_tag_id, Model model) {
        jdbcTemplate.update("update bind set bind_delete = 1 where bind_tag_id = ?", bind_tag_id);
    }

    public String deleteBindByTagIdAndPatientId(int bind_patient_id, int bind_tag_id, int oid, int role, Model model) {
        String auth_flag = authDelete(bind_tag_id, oid, role);
        if(auth_flag != "pass"){ // 权限控制
            model.addAttribute("pb_message", auth_flag);
        }
        else {
            jdbcTemplate.update("update bind set bind_start_time = '1900-01-01 00:00:00', bind_end_time = '1900-01-01 00:00:00' " +
                    "where bind_patient_id = ? and bind_tag_id= ?", bind_patient_id, bind_tag_id);
            model.addAttribute("pb_message", "解绑成功");
        }
        return getBindPageByPatientId(bind_patient_id, model);
    }

    public String getBindById(int bind_id, Model model) {
        autoDeleteTimeOutBind();//自动删除不在当前时间内生效的绑定
        return jdbcTemplate.queryForMap("select * from bind where bind_id = ? and bind_delete != 1", bind_id).toString();
    }

    public List<Tag> getBindByPatientId(int bind_patient_id) {
        autoDeleteTimeOutBind();//自动删除不在当前时间内生效的绑定
        String sql = "select * from tag where tag_id in (" +
                "select bind_tag_id from bind where bind_patient_id = "+bind_patient_id+" and bind_delete != 1 and  " +
                "bind_start_time <= now() and  bind_end_time >= now())";
        List<Tag> list =new ArrayList();
        list = jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(Tag.class));
        return list;
//        if(redisService.patientIdExist(bind_patient_id)){//先判断缓存中是否存在
//            System.out.println("缓存中取数据bpiFindbti"+Integer.toString(bind_patient_id));
//            return redisService.getSet("bpiFindbti"+Integer.toString(bind_patient_id)).toString();//存在直接取
//        }
//        else {//不存在去mysql里取，取后放入缓存
//            return getMySQL_bpiFindbti_toRedis(bind_patient_id);
//        }
        }

    public String getBindPageByPatientId(int bind_patient_id, Model model) {
        autoDeleteTimeOutBind();//自动删除不在当前时间内生效的绑定
        String sql="select * from tag \n" +
                "where tag_delete !=1 and tag_id in (\n" +
                "select bind_tag_id from bind where bind_patient_id = ? and bind_delete != 1);";
        RowMapper<Tag> rowTagMapper=new BeanPropertyRowMapper<Tag>(Tag.class);
        model.addAttribute("tagListOfPatient", jdbcTemplate.query(sql, rowTagMapper, bind_patient_id));//该病人的标签
        model.addAttribute("tagList", jdbcTemplate.queryForList("select * from tag where tag_delete!=1"));//所有标签
        RowMapper<Patient> rowPatientMapper=new BeanPropertyRowMapper<Patient>(Patient.class);
        Patient patient = jdbcTemplate.queryForObject("select * from tb_patient where id = ?", rowPatientMapper,bind_patient_id);
        model.addAttribute("patient", patient);
        return "patientBind";
    }

    public String getBindByTagId(int bind_tag_id) {
        autoDeleteTimeOutBind();//自动删除不在当前时间内生效的绑定
        if(redisService.tagIdExist(bind_tag_id)){//先判断缓存中是否存在
            System.out.println("缓存中取数据");
            return redisService.getSet("btiFindbpi"+Integer.toString(bind_tag_id)).toString();//存在直接取
        }
        else {//不存在去mysql里取，取后放入缓存
            return getMySQL_btiFindbpi_toRedis(bind_tag_id);
        }
    }

    public List<Tag> getMySQL_bpiFindbti_toRedis(int bind_patient_id){  //封装方法从数据库中读 写入 Redis
//        System.out.println("数据库中找数据并存入缓存");
        List<Tag> list =  jdbcTemplate.queryForList("select * from bind where bind_patient_id = ? and bind_delete != 1 and  " +
                "bind_start_time <= now() and  bind_end_time >= now()", Tag.class, bind_patient_id);
        return list;
//        for(int i=0;i<binds.size();i++){
//            Map bindMap=binds.get(i);
//            redisService.putSet("bpiFindbti"+Integer.toString(bind_patient_id), Integer.toString((Integer) bindMap.get("bind_tag_id")));
//        }
    }

    public String getMySQL_btiFindbpi_toRedis(int bind_tag_id){  //封装方法从数据库中读 写入 Redis
        System.out.println("数据库中找数据并存入缓存");
        List  <Map<String, Object>> binds= jdbcTemplate.queryForList("select * from bind where bind_tag_id = ? and bind_delete != 1 and " +
                "bind_start_time <= now() and  bind_end_time >= now()", bind_tag_id);//是否在期限内

        for(int i=0;i<binds.size();i++){
            Map bindMap=binds.get(i);
            redisService.putSet("btiFindbpi"+Integer.toString(bind_tag_id), Integer.toString((Integer) bindMap.get("bind_patient_id")));
        }
        return binds.toString();
    }

    public void autoDeleteTimeOutBind(){//删除所有不在时间内的,恢复到达时间范围内的绑定
        jdbcTemplate.update("update bind set bind_delete = 1  where bind_start_time > now() or  bind_end_time < now();");
        jdbcTemplate.update("update bind set bind_delete = 0  where bind_start_time <= now() and  bind_end_time >= now() and bind_delete = 1;");
    }

    public String getBindPage(int bind_patient_id, int bind_tag_id, int oid, int role, Model model) {
        String auth_flag = authCreate(bind_tag_id, oid, role);
        if(auth_flag != "pass"){ // 权限控制
            model.addAttribute("pb_message", auth_flag);
            return getBindPageByPatientId(bind_patient_id, model);
        }
        RowMapper<Patient> rowPatientMapper=new BeanPropertyRowMapper<Patient>(Patient.class);
        Patient patient = jdbcTemplate.queryForObject("select * from tb_patient where id = ?", rowPatientMapper,bind_patient_id);
        model.addAttribute("patient", patient);
        RowMapper<Tag> rowTagMapper=new BeanPropertyRowMapper<Tag>(Tag.class);
        Tag tag = jdbcTemplate.queryForObject("select * from tag where tag_id = ?", rowTagMapper,bind_tag_id);
        model.addAttribute("tag", tag);
        return "forward:bindPage";
    }

    public String getBindPageByTagIdAndPatientId(int bind_patient_id, int bind_tag_id, int oid, int role, Model model) {
        String auth_flag = authUpdate(bind_tag_id, oid, role);
        if(auth_flag != "pass"){ // 权限控制
            model.addAttribute("pb_message", auth_flag);
            return getBindPageByPatientId(bind_patient_id, model);
        }
        RowMapper<Patient> rowPatientMapper=new BeanPropertyRowMapper<Patient>(Patient.class);
        Patient patient = jdbcTemplate.queryForObject("select * from tb_patient where id = ?", rowPatientMapper,bind_patient_id);
        model.addAttribute("patient", patient);
        RowMapper<Tag> rowTagMapper=new BeanPropertyRowMapper<Tag>(Tag.class);
        Tag tag = jdbcTemplate.queryForObject("select * from tag where tag_id = ?", rowTagMapper,bind_tag_id);
        model.addAttribute("tag", tag);
        RowMapper<Bind> rowBindMapper=new BeanPropertyRowMapper<Bind>(Bind.class);
        String sql = "select * from bind where bind_patient_id = "+ bind_patient_id + " and " +
                "bind_tag_id = "+bind_tag_id;
        Bind bind = jdbcTemplate.queryForObject(sql, rowBindMapper);
        model.addAttribute("bind", bind);
        return "forward:bindPage";
    }

    public boolean isSex(int bind_patient_id){//是否已存在性别
        if(jdbcTemplate.queryForObject("select count(1) from bind" +
                " where (bind_tag_id = 1 or bind_tag_id = 2) and bind_delete != 1 and bind_patient_id = "+ Integer.toString(bind_patient_id), Integer.class)>0){
            return true;
        }
        return false;
    }

    private String authCreate(int tag_id, int oid, int role) {// 创建标签权限控制
        Tag tag = tagService.getTagById(tag_id);
        int tag_group = tag.getTag_group();
        int tag_office = tag.getTag_office();
        int tag_weight = tag.getTag_weight();
        if(tag_group > role+1){// 分组
            return "权限不足";
        }
        if(tag_office != oid && tag_office != 8){// 科室
            return "您只能绑定您所在科室的标签";
        }
        if(role+1 < tag_weight){
            return "权限不足";
        }
        return "pass";
    }
    private String authUpdate(int tag_id, int oid, int role) {// 创建标签权限控制
        Tag tag = tagService.getTagById(tag_id);
        int tag_group = tag.getTag_group();
        int tag_office = tag.getTag_office();
        int tag_weight = tag.getTag_weight();
        if(tag_group > role+1){// 分组
            return "权限不足";
        }
        if(tag_office != oid && tag_office != 8){// 科室
            return "您只能编辑您所在科室的标签";
        }
        if(role+1 < tag_weight){
            return "权限不足";
        }
        return "pass";
    }

    private String authDelete(int tag_id, int oid, int role) {// 创建标签权限控制
        Tag tag = tagService.getTagById(tag_id);
        int tag_group = tag.getTag_group();
        int tag_office = tag.getTag_office();
        int tag_weight = tag.getTag_weight();
        if(tag_group > role+1){// 分组
            return "权限不足";
        }
        if(tag_office != oid && tag_office != 8){// 科室
            return "您只能删除您所在科室的标签";
        }
        if(role+1 < tag_weight){
            return "权限不足";
        }
        return "pass";
    }
}
